home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Atlanta_1990 / Atlanta-Devcon.2 / AppShell / examples / WatchMan / wm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-26  |  17.0 KB  |  620 lines

  1. /*
  2.  * Copyright (C) 1990 Commodore-Amiga, Inc. All rights reserved
  3.  */
  4.  
  5. /*
  6.  * WatchMan. Watches files for changes. Example Appshell application
  7.  */
  8.  
  9. #include <libraries/appshell.h>
  10. #include <clib/appshell_protos.h>
  11.  
  12. #include "fn_handler.h"
  13. #include "wm.h"
  14.  
  15. extern LONG     _stack = 4000;
  16. extern UBYTE   *_procname = APPNAME;
  17. extern LONG     _priority = 0;
  18. extern LONG     _BackGroundIO = 0;
  19. extern LONG     _Backstdout;
  20.  
  21. struct FilePart {
  22.     struct PoolHeader *ph;
  23.     struct List    *filelist;
  24.     struct List    *flaglist;
  25.     LONG            Retries;
  26.     LONG            Interval;
  27.     LONG            Flags;
  28.     UBYTE           FlagDesc[12];
  29.     UBYTE           Filename[512];
  30. };
  31.  
  32. UBYTE          *flagdescr[] =
  33. {
  34.     "FN_CREATED",
  35.     "FN_DELETED",
  36.     "FN_SMALLER",
  37.     "FN_BIGGER",
  38.     "FN_NEWER",
  39.     "FN_MUSTEXIST",
  40. };
  41.  
  42. extern struct WBStartup *WBenchMsg;
  43.  
  44. VOID 
  45. main(int argc, char **argv)
  46. {
  47.  
  48.     if (_Backstdout) {
  49.     Close(_Backstdout);
  50.     _Backstdout = 0;
  51.     }
  52.     HandleApp(argc, argv, WBenchMsg, WM);
  53. }
  54.  
  55. /* Custom application init. Setup local lists etc. */
  56. VOID 
  57. WMInitFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  58. {
  59.     struct FilePart *fp;
  60.     struct Node    *node;
  61.     LONG            w, g;
  62.     int             i;
  63.  
  64.     if (fp = AllocVec(sizeof(struct FilePart), MEMF_CLEAR)) {
  65.     if (fp->ph = CreatePrivatePool(MEMF_CLEAR, 2048, 128)) {
  66.         fp->filelist = AllocPooled(sizeof(struct List), fp->ph);
  67.         fp->flaglist = AllocPooled(sizeof(struct List), fp->ph);
  68.         NewList(fp->filelist);
  69.         NewList(fp->flaglist);
  70.  
  71.         /* Fill in the list for available flags */
  72.         for (i = 0; i < 6; i++) {
  73.         node = AllocPooled(sizeof(struct Node), fp->ph);
  74.         node->ln_Name = AllocPooled(strlen(flagdescr[i]) + 1, fp->ph);
  75.         strcpy(node->ln_Name, flagdescr[i]);
  76.         AddTail(fp->flaglist, node);
  77.         }
  78.         /* And update the listview gadget */
  79.         if (APSHGetGadgetInfo(ai, "MAIN", "FLAGLIST", &w, &g)) {
  80.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  81.                   GTLV_Labels, fp->flaglist,
  82.                   GTLV_Top, 0,
  83.                   TAG_DONE);
  84.  
  85.         }
  86.         /* Use ai->ai_UserData to pass structure around */
  87.         ai->ai_UserData = fp;
  88.     } else {
  89.         FreeVec(fp);
  90.     }
  91.     }
  92. }
  93.  
  94. /* Custom application exit, free resources */
  95. VOID 
  96. WMExitFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  97. {
  98.  
  99.     struct FilePart *fp;
  100.     struct Node    *wnode, *nnode;
  101.  
  102.     if (ai->ai_UserData) {
  103.     /* Get pointer to application structure */
  104.     fp = (struct FilePart *) ai->ai_UserData;
  105.     if (fp->ph) {
  106.         /* Free the lists and free the pool. */
  107.         wnode = (struct Node *) fp->filelist->lh_Head;
  108.         while (nnode = (struct Node *) (wnode->ln_Succ)) {
  109.         FreePooled(wnode->ln_Name, fp->ph);
  110.         Remove(wnode);
  111.         FreePooled(wnode, fp->ph);
  112.         wnode = nnode;
  113.         }
  114.         FreePooled(fp->filelist, fp->ph);
  115.         wnode = (struct Node *) fp->flaglist->lh_Head;
  116.         while (nnode = (struct Node *) (wnode->ln_Succ)) {
  117.         FreePooled(wnode->ln_Name, fp->ph);
  118.         Remove(wnode);
  119.         FreePooled(wnode, fp->ph);
  120.         wnode = nnode;
  121.         }
  122.         FreePooled(fp->flaglist, fp->ph);
  123.         DeletePrivatePool(fp->ph);
  124.     }
  125.     FreeVec(fp);
  126.     }
  127. }
  128.  
  129. VOID 
  130. WMAboutFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  131. {
  132.     struct FilePart *fp = ai->ai_UserData;
  133.     STRPTR          buffer;
  134.  
  135.     /*
  136.      * Simple fill a buffer and call NotifyUser() to put up a nice requester.
  137.      */
  138.     if (buffer = AllocPooled(512, fp->ph)) {
  139.     sprintf(buffer, "%s\n\n%s\n\n%s",
  140.         ai->ai_AppVersion,
  141.         ai->ai_AppCopyright,
  142.         ai->ai_AppAuthor);
  143.  
  144.     NotifyUser(ai, buffer, NULL);
  145.     FreePooled(buffer, fp->ph);
  146.     }
  147. }
  148.  
  149. /* Application function called by fn_handler */
  150. VOID 
  151. FileNotification(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  152. {
  153.     struct FNData  *fndata;
  154.     struct FilePart *fp = (struct FilePart *) ai->ai_UserData;
  155.     struct Node    *node;
  156.     ULONG           w, g;
  157.     UBYTE          *buffer;
  158.  
  159.     /*
  160.      * When the handler calls us, it passes the pointer to the relevant data
  161.      * as tag data
  162.      */
  163.  
  164.     fndata = (struct FNData *) GetTagData(APSH_CmdData, NULL, tl);
  165.  
  166.     /* Fill in a buffer and put up a cool requester */
  167.     buffer = AllocPooled(300, fp->ph);
  168.     sprintf(buffer, "File Notification!\n\nTarget: %s\nStatus: %s%s%s%s%s%s",
  169.         fndata->fnd_Filename,
  170.         (fndata->fnd_Status & FN_DONE) ? "DONE " : NULL,
  171.         (fndata->fnd_Status & FN_CREATED) ? "CREATED " : NULL,
  172.         (fndata->fnd_Status & FN_DELETED) ? "DELETED " : NULL,
  173.         (fndata->fnd_Status & FN_SMALLER) ? "SMALLER " : NULL,
  174.         (fndata->fnd_Status & FN_BIGGER) ? "BIGGER " : NULL,
  175.         (fndata->fnd_Status & FN_NEWER) ? "NEWER" : NULL);
  176.  
  177.     NotifyUser(ai, buffer, NULL);
  178.     FreePooled(buffer, fp->ph);
  179.  
  180.     /*
  181.      * If the handler tells us the number of retries for the target has been
  182.      * reached, try to remove the target from the list and listview gadget.
  183.      * If the window is hidden, we cannot touch the gadget, so we'll leave a
  184.      * false entry. That will be dealt with when the user tries to re-delete
  185.      * the target
  186.      */
  187.  
  188.     if (fndata->fnd_Status & FN_DONE) {
  189.     if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
  190.         /*
  191.          * Detach the list from the listview gadget, so we can update the
  192.          * list
  193.          */
  194.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  195.                   GTLV_Labels, ~0,
  196.                   TAG_DONE);
  197.  
  198.         /* If it's there, remove it */
  199.         if (node = FindName(fp->filelist, fp->Filename)) {
  200.         FreePooled(node->ln_Name, fp->ph);
  201.         Remove(node);
  202.         FreePooled(node, fp->ph);
  203.         }
  204.         /* And attach the list to the listview gadget again */
  205.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  206.                   GTLV_Labels, fp->filelist,
  207.                   GTLV_Top, 0,
  208.                   TAG_DONE);
  209.     }
  210.     }
  211. }
  212.  
  213.  
  214. void 
  215. SetFilenameFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  216. {
  217.     struct FilePart *fp = ai->ai_UserData;
  218.     struct Gadget  *gadget;
  219.     struct WBArg   *wbarg;
  220.     STRPTR          buffer = NULL;
  221.     STRPTR          entry;
  222.     STRPTR          parsedline;
  223.     STRPTR          argv[MAXARG];
  224.     ULONG           argc = 0;
  225.     ULONG           w, g;
  226.  
  227.     if (str) {
  228.     parsedline = BuildParseLine(str, &argc, argv);
  229.     }
  230.     if (argc >= 2) {
  231.     /* We're called with a string argument, via AREXX or cmdshell */
  232.     entry = argv[1];
  233.     if (APSHGetGadgetInfo(ai, "MAIN", "FSTRING", &w, &g)) {
  234.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  235.                   GTST_String, entry,
  236.                   TAG_DONE);
  237.     }
  238.     } else {
  239.     gadget = (struct Gadget *) GetTagData(APSH_MsgIAddress, NULL, tl);
  240.     if (gadget)
  241.         entry = ((STRPTR) ((struct StringInfo *) (gadget)->SpecialInfo)->Buffer);
  242.     else {
  243.         /* WB drop support */
  244.         wbarg = (struct WBArg *) GetTagData(APSH_WBArg, NULL, tl);
  245.         buffer = AllocPooled(512, fp->ph);
  246.         /*
  247.          * WB passes a lock to the directory and a pointer to the
  248.          * filename which was dropped.
  249.          */
  250.         if (NameFromLock(wbarg->wa_Lock, buffer, 512)) {
  251.         entry = wbarg->wa_Name;
  252.         if (AddPart(buffer, entry, 512))
  253.             entry = buffer;
  254.         } else
  255.         entry = NULL;
  256.         if (APSHGetGadgetInfo(ai, "MAIN", "FSTRING", &w, &g)) {
  257.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  258.                   GTST_String, entry,
  259.                   TAG_DONE);
  260.         }
  261.     }
  262.  
  263.     /* Activate next gadget, it seems logical */
  264.     if (APSHGetGadgetInfo(ai, "MAIN", "ISTRING", &w, &g))
  265.         ActivateGadget((struct Gadget *) g, (struct Window *) w, NULL);
  266.     }
  267.     strcpy(fp->Filename, entry);
  268.     if (buffer)
  269.     FreePooled(buffer, fp->ph);
  270.     if (str)
  271.     FreeParseLine(parsedline);
  272. }
  273.  
  274.  
  275. void 
  276. SetRetriesFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  277. {
  278.     struct FilePart *fp = ai->ai_UserData;
  279.     struct Gadget  *gadget;
  280.     LONG            retries;
  281.     STRPTR          parsedline;
  282.     STRPTR          argv[MAXARG];
  283.     ULONG           argc;
  284.     ULONG           w, g;
  285.  
  286.     if (str) {
  287.     parsedline = BuildParseLine(str, &argc, argv);
  288.     }
  289.     if (argc >= 2) {
  290.     stcd_l(argv[1], &retries);
  291.     if (APSHGetGadgetInfo(ai, "MAIN", "RSTRING", &w, &g)) {
  292.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  293.                   GTIN_Number, retries,
  294.                   TAG_DONE);
  295.     }
  296.     } else {
  297.     gadget = (struct Gadget *) GetTagData(APSH_MsgIAddress, NULL, tl);
  298.     retries = ((LONG) ((struct StringInfo *) (gadget)->SpecialInfo)->LongInt);
  299.     }
  300.     fp->Retries = retries;
  301.     if (str)
  302.     FreeParseLine(parsedline);
  303. }
  304.  
  305.  
  306. void 
  307. SetIntervalFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  308. {
  309.     struct FilePart *fp = ai->ai_UserData;
  310.     struct Gadget  *gadget;
  311.     LONG            interval;
  312.     STRPTR          argv[MAXARG];
  313.     STRPTR          parsedline;
  314.     ULONG           argc = 0;
  315.     ULONG           w, g;
  316.  
  317.     if (str) {
  318.     parsedline = BuildParseLine(str, &argc, argv);
  319.     }
  320.     if (argc >= 2) {
  321.     stcd_l(argv[1], &interval);
  322.     if (APSHGetGadgetInfo(ai, "MAIN", "ISTRING", &w, &g)) {
  323.         /*
  324.          * Currently GadTools doesn't allow signed numbers, so negatives
  325.          * come out 'weird'.
  326.          */
  327.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  328.                   GTIN_Number, interval,
  329.                   TAG_DONE);
  330.     }
  331.     } else {
  332.     gadget = (struct Gadget *) GetTagData(APSH_MsgIAddress, NULL, tl);
  333.     interval = ((LONG) ((struct StringInfo *) (gadget)->SpecialInfo)->LongInt);
  334.     /* Activate next gadget, it seems logical */
  335.     if (APSHGetGadgetInfo(ai, "MAIN", "RSTRING", &w, &g))
  336.         ActivateGadget((struct Gadget *) g, (struct Window *) w, NULL);
  337.     }
  338.     fp->Interval = interval;
  339.     if (str)
  340.     FreeParseLine(parsedline);
  341. }
  342.  
  343.  
  344. void 
  345. SetFlagsFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  346. {
  347.  
  348.     struct FilePart *fp = ai->ai_UserData;
  349.     USHORT          code;
  350.     STRPTR          parsedline;
  351.     ULONG           argc;
  352.     STRPTR          argv[MAXARG];
  353.     ULONG           w, g;
  354.  
  355.     if (str)
  356.     parsedline = BuildParseLine(str, &argc, argv);
  357.     if (argc >= 2) {
  358.         /* We're called with a string argment, like 
  359.          * "setflags fn_newer|fn_mustexist"
  360.          */
  361.     if (MatchValue(argv[1], "FN_MUSTEXIST"))
  362.         fp->Flags ^= FN_MUSTEXIST;
  363.     if (MatchValue(argv[1], "FN_CREATED"))
  364.         fp->Flags ^= FN_CREATED;
  365.     if (MatchValue(argv[1], "FN_DELETED"))
  366.         fp->Flags ^= FN_DELETED;
  367.     if (MatchValue(argv[1], "FN_SMALLER"))
  368.         fp->Flags ^= FN_SMALLER;
  369.     if (MatchValue(argv[1], "FN_BIGGER"))
  370.         fp->Flags ^= FN_BIGGER;
  371.     if (MatchValue(argv[1], "FN_NEWER"))
  372.         fp->Flags ^= FN_NEWER;
  373.     } else {
  374.         /* Tags then? */
  375.     code = (USHORT) GetTagData(APSH_MsgCode, 10, tl);
  376.  
  377.     switch (code) {
  378.     case 0:
  379.         fp->Flags ^= FN_CREATED;
  380.         break;
  381.     case 1:
  382.         fp->Flags ^= FN_DELETED;
  383.         break;
  384.     case 2:
  385.         fp->Flags ^= FN_SMALLER;
  386.         break;
  387.     case 3:
  388.         fp->Flags ^= FN_BIGGER;
  389.         break;
  390.     case 4:
  391.         fp->Flags ^= FN_NEWER;
  392.         break;
  393.     case 5:
  394.         fp->Flags ^= FN_MUSTEXIST;
  395.         break;
  396.     default:
  397.         break;
  398.     }
  399.     }
  400.  
  401.     /* Put the flag letters in a fixed buffer and show it, if possible */
  402.     sprintf(fp->FlagDesc, "%s%s%s%s%s%s",
  403.         (fp->Flags & FN_CREATED) ? "C " : NULL,
  404.         (fp->Flags & FN_DELETED) ? "D " : NULL,
  405.         (fp->Flags & FN_SMALLER) ? "S " : NULL,
  406.         (fp->Flags & FN_BIGGER) ? "B " : NULL,
  407.         (fp->Flags & FN_NEWER) ? "N " : NULL,
  408.         (fp->Flags & FN_MUSTEXIST) ? "M" : NULL);
  409.  
  410.     if (APSHGetGadgetInfo(ai, "MAIN", "SHOWTEXT", &w, &g)) {
  411.     GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  412.               GTTX_Text, fp->FlagDesc,
  413.               TAG_DONE);
  414.     }
  415.     if (str)
  416.     FreeParseLine(parsedline);
  417. }
  418.  
  419. /* Accept the choice in the 'target' listview as general filename */
  420. void 
  421. GetFileFromListFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  422. {
  423.     struct FilePart *fp = ai->ai_UserData;
  424.     struct Node    *node;
  425.     USHORT          code;
  426.     ULONG           w, g;
  427.     int             i;
  428.  
  429.     code = GetTagData(APSH_MsgCode, 0, tl);
  430.  
  431.     if (code != 32) {
  432.         /* Actually selected a target */
  433.     node = fp->filelist->lh_Head;
  434.     for (i = 0; i < code; i++)
  435.         node = node->ln_Succ;
  436.  
  437.         /* Make choice general target */
  438.     strcpy(fp->Filename, node->ln_Name);
  439.  
  440.         /* Update the filename string gadget, if possible */
  441.     if (APSHGetGadgetInfo(ai, "MAIN", "FSTRING", &w, &g)) {
  442.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  443.                   GTST_String, fp->Filename,
  444.                   TAG_DONE);
  445.     }
  446.     }
  447. }
  448.  
  449. /* Put in a request to the handler to add a target */
  450. VOID 
  451. AddTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  452. {
  453.     struct FilePart *fp = ai->ai_UserData;
  454.     struct Node    *node;
  455.     ULONG           w, g;
  456.     BOOL            error = 0;
  457.  
  458.     /* Call the handler function, because it's called with all
  459.      * tags (even if they're NULL) we don't actually use the
  460.      * handlers defaults.
  461.      */
  462.  
  463.     FileNotify(ai, NULL,
  464.            FN_Command, FN_ADDTARGET,
  465.            FN_Filename, fp->Filename,
  466.            FN_Interval, fp->Interval,
  467.            FN_Retries, fp->Retries,
  468.            FN_Flags, fp->Flags,
  469.            FN_Error, &error,
  470.            TAG_DONE);
  471.  
  472.     if (error == 0) {
  473.         /* Handler accepted the request, try to make it visible */
  474.     if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
  475.             /* Detach the list from the listview gadget, so it can
  476.              * be updated.
  477.              */
  478.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  479.                   GTLV_Labels, ~0,
  480.                   TAG_DONE);
  481.  
  482.             /* If it's not there already, add a new node */
  483.         if (!(node = FindName(fp->filelist, fp->Filename))) {
  484.         node = AllocPooled(sizeof(struct Node), fp->ph);
  485.         node->ln_Name = AllocPooled(strlen(fp->Filename) + 1, fp->ph);
  486.         strcpy(node->ln_Name, fp->Filename);
  487.         AddTail(fp->filelist, node);
  488.         }
  489.             /* And attach the list to the listview gadget again */
  490.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  491.                   GTLV_Labels, fp->filelist,
  492.                   GTLV_Top, 0,
  493.                   TAG_DONE);
  494.     }
  495.     }
  496. }
  497.  
  498.  
  499. /* Put in a request to the handler to stop watching a target */
  500. VOID 
  501. DelTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  502. {
  503.     struct FilePart *fp = ai->ai_UserData;
  504.     struct Node    *node;
  505.     ULONG           w, g;
  506.     BOOL            error;
  507.  
  508.     /* Call handler function with the target name which should be 
  509.      * removed from the list */
  510.     FileNotify(ai, NULL,
  511.            FN_Command, FN_DELTARGET,
  512.            FN_Filename, fp->Filename,
  513.            FN_Error, &error,
  514.            TAG_DONE);
  515.  
  516.     /* Even if the handler doesn't know the target and complains,
  517.      * remove it from the list, the user doesn't want it anymore.
  518.      */
  519.  
  520.     /* Detach the list from the listview gadget, so it can be updated */
  521.     if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
  522.     GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  523.               GTLV_Labels, ~0,
  524.               TAG_DONE);
  525.  
  526.         /* Remove the node from the list if it's found */
  527.     if (node = FindName(fp->filelist, fp->Filename)) {
  528.         FreePooled(node->ln_Name, fp->ph);
  529.         Remove(node);
  530.         FreePooled(node, fp->ph);
  531.     }
  532.         /* Attach the list to the listview gadget again */
  533.     GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  534.               GTLV_Labels, fp->filelist,
  535.               GTLV_Top, 0,
  536.               TAG_DONE);
  537.     }
  538. }
  539.  
  540.  
  541. /* Put in a request to sync a target */
  542. VOID 
  543. SyncTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  544. {
  545.  
  546.     struct FilePart *fp = ai->ai_UserData;
  547.     struct Node    *node;
  548.     ULONG           w, g;
  549.     BOOL            error;
  550.  
  551.     /* Call the handler function */
  552.     FileNotify(ai, NULL,
  553.            FN_Command, FN_SYNC,
  554.            FN_Filename, fp->Filename,
  555.            FN_Error, &error,
  556.            TAG_DONE);
  557.  
  558.     /*
  559.      * If sync failed, try to remove it from the list. It's probably removed
  560.      * thru the shell or arexx.
  561.      */
  562.  
  563.     if (error) {
  564.         /* Detach list from the listview gadget so it can be updated */
  565.     if (APSHGetGadgetInfo(ai, "MAIN", "FILELIST", &w, &g)) {
  566.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  567.                   GTLV_Labels, ~0,
  568.                   TAG_DONE);
  569.  
  570.             /* Remove node from the list if found */
  571.         if (node = FindName(fp->filelist, fp->Filename)) {
  572.         FreePooled(node->ln_Name, fp->ph);
  573.         Remove(node);
  574.         FreePooled(node, fp->ph);
  575.         }
  576.             /* Attach list to the listview gadget again */
  577.         GT_SetGadgetAttrs((struct Gadget *) g, (struct Window *) w, NULL,
  578.                   GTLV_Labels, fp->filelist,
  579.                   GTLV_Top, 0,
  580.                   TAG_DONE);
  581.     }
  582.     }
  583. }
  584.  
  585. VOID 
  586. InquiryTargetFunc(struct AppInfo * ai, STRPTR str, struct TagItem * tl)
  587. {
  588.     struct FilePart *fp = ai->ai_UserData;
  589.     struct FNData  *fndata;
  590.     BOOL            error;
  591.     STRPTR          buffer;
  592.  
  593.     fndata = AllocPooled(sizeof(struct FNData), fp->ph);
  594.  
  595.     FileNotify(ai, NULL,
  596.            FN_Command, FN_INQUIRY,
  597.            FN_Filename, fp->Filename,
  598.            FN_Error, &error,
  599.            FN_Buffer, fndata,
  600.            TAG_DONE);
  601.  
  602.     if (!(error)) {
  603.     buffer = AllocPooled(300, fp->ph);
  604.     sprintf(buffer, "Target: %s\nInterval: %ld\nRetries: %ld\nFlags: %s%s%s%s%s%s",
  605.         fndata->fnd_Filename,
  606.         fndata->fnd_Interval,
  607.         fndata->fnd_Retries,
  608.         (fndata->fnd_Flags & FN_CREATED) ? "FN_CREATED " : NULL,
  609.         (fndata->fnd_Flags & FN_DELETED) ? "FN_DELETED " : NULL,
  610.         (fndata->fnd_Flags & FN_SMALLER) ? "FN_SMALLER " : NULL,
  611.         (fndata->fnd_Flags & FN_BIGGER) ? "FN_BIGGER " : NULL,
  612.         (fndata->fnd_Flags & FN_NEWER) ? "FN_NEWER " : NULL,
  613.         (fndata->fnd_Flags & FN_MUSTEXIST) ? "FN_MUSTEXIST " : NULL);
  614.  
  615.     NotifyUser(ai, buffer, NULL);
  616.     FreePooled(buffer, fp->ph);
  617.     }
  618.     FreePooled(fndata, fp->ph);
  619. }
  620.